package webserver;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import utils.Utils;
import webserver.iterfaces.IHttpResponse;

import compiller.CompileCodeFromPage;

import dao.DAO;

public class PageDispatcher {

	private static final String DEFAULT_OS_DELIMITER = "/";
	private static File file = new File(Consts.PATH_TO_WEB);

	private CompileCodeFromPage compiller = new CompileCodeFromPage(
			DAO.getInstance());

	public IHttpResponse dispatch(HttpRequest rq) {
		if (rq == null)
			throw new Error();
		if (rq.getPage() == null) {
			throw new Error();
		}
		String pageName = rq.getPage().replace("\\", DEFAULT_OS_DELIMITER);
		if (!pageName.equals(Consts.INDEX)) {
			String ext;
			ext = getExt(pageName);
			String type = Consts.MIME_TYPES.get(ext);
			if (type != null) {
				return processNotIndex(rq, pageName, type);
			} else {
				return error("No right file");
			}
		} else {
			return processIndex(rq);
		}
	}

	private String getExt(String pageName) {
		String[] extArray = pageName.split("\\.");
		if (extArray.length > 1) {
			return "." + extArray[extArray.length - 1];
		} else {
			return null;
		}
	}

	private IHttpResponse processIndex(HttpRequest rq) {
		File[] listFiles = file.listFiles(new FileFilter() {

			@Override
			public boolean accept(File file) {
				return file.getName().startsWith("index") && file.isFile();
			}
		});
		if (listFiles != null && listFiles.length > 0) {
			File index = listFiles[0];
			return processResult(rq, index);
		} else {
			return error("No index found");
		}
	}

	private IHttpResponse processNotIndex(HttpRequest rq, String pageName,
			String type) {
		if (type != null) {
			String[] split = pageName.split(DEFAULT_OS_DELIMITER);
			File currentFile = file;
			for (final String fName : split) {
				File[] listFiles = currentFile.listFiles(new FilenameFilter() {
					@Override
					public boolean accept(File dir, String name) {
						return name.equals(fName);
					}
				});
				if (listFiles.length > 0) {
					currentFile = listFiles[0];
				} else {
					return error("Not Found");
				}
			}
			return processResult(rq, currentFile);
			// error("Not impl yet" + type, httpResponse);
		} else {
			return error("Unsupported page");
		}
	}

	private static final Pattern JAVA_SECTION = Pattern.compile(
			"<\\?java (.*?)\\?java>", Pattern.DOTALL | Pattern.MULTILINE);

	private IHttpResponse processResult(HttpRequest rq, File file) {
		if (file.isFile()) {
			httpResponse.setCode(200);
			String ext = getExt(file.getPath());
			String contentType = Consts.MIME_TYPES.get(ext);
			if (contentType == null) {
				contentType = Consts.MIME_TYPES.get(".html");
			}
			httpResponse.setContentType(contentType);
			if (contentType.contains("text")) {
				loadTextPage(rq, httpResponse, file, ext);
			} else {
				loadImgPage(rq, httpResponse, file, ext);
			}
		} else {
			error("Not file", httpResponse);
		}
	}
	
	

	private void loadImgPage(HttpRequest rq, HttpTextResponse httpResponse,
			File file, String ext) {

	}

	private void loadTextPage(HttpRequest rq, HttpTextResponse httpResponse,
			File file, String ext) {
		String result = Utils.deserializeString(file);
		if (ext.equals(Consts.COMPILED_PAGE_EXTENSION)) {
			Matcher matcher = JAVA_SECTION.matcher(result);
			StringBuffer sb = new StringBuffer();
			while (matcher.find()) {
				String javaCode = matcher.group(1);
				String invokedResult;
				try {
					invokedResult = compiller.invoke(javaCode, rq);
				} catch (Exception e) {
					e.printStackTrace();
					throw new RuntimeException(e);
				}
				matcher.appendReplacement(sb, invokedResult);
			}
			matcher.appendTail(sb);
			result = sb.toString();
		}
		httpResponse.setResultPage(result);
	}

	private IHttpResponse error(String msg) {
		return new HttpTextResponse().setCode(404).setResultPage(msg);
	}
}
